Este documento presenta un análisis exploratorio completo del conjunto de datos que abarca información del período 2009-2023.
Resumen del Dataset:
# Diccionario de datos - Significado de cada variable
diccionario_variables <- data.frame(
Variable = c(
"DEPREG", "MUPREG", "MESREG", "AÑOREG",
"DEPOCU", "MUPOCU", "AREAG",
"SEXO", "DIAOCU", "MESOCU", "AÑOOCU",
"TIPAR", "CLAPAR", "VIAPAR",
"SEMGES", "EDADM",
"DEPREM", "MUPREM", "GRETNM", "ESCIVM",
"NACIOM", "OCUPAM", "ESCOLAM",
"PAISREM", "PUEBLOPM", "CIUOMAD", "NACIONM",
"CAUDEF", "ASISREC", "SITIOOCU",
"TOHITE", "TOHINM", "TOHIVI"
),
Significado = c(
"Departamento de registro",
"Municipio de registro",
"Mes de registro",
"Año de registro",
"Departamento de ocurrencia",
"Municipio de ocurrencia",
"Área geográfica (1=Urbana, 2=Rural)",
"Sexo del fallecido (1=Masculino, 2=Femenino, 9=No especificado)",
"Día de ocurrencia",
"Mes de ocurrencia",
"Año de ocurrencia",
"Tipo de parto",
"Clasificación del parto",
"Vía del parto",
"Semanas de gestación",
"Edad de la madre (en años)",
"Departamento de residencia de la madre",
"Municipio de residencia de la madre",
"Grupo étnico de la madre",
"Estado civil de la madre",
"Nacionalidad de la madre",
"Ocupación de la madre",
"Escolaridad de la madre (años de estudio)",
"País de residencia de la madre",
"Pueblo/comunidad indígena de la madre",
"Ciudad o municipio de residencia de la madre",
"Nacionalidad de la madre (código)",
"Causa de defunción (código CIE-10)",
"Asistencia recibida (1=Sí, 2=No)",
"Sitio de ocurrencia del parto",
"Total de hijos tenidos",
"Total de hijos nacidos muertos",
"Total de hijos nacidos vivos"
),
stringsAsFactors = FALSE
)
diccionario_variables %>%
kable(
caption = "Tabla 1: Diccionario de Datos - Significado de Variables",
col.names = c("Variable", "Descripción/Significado"),
align = c('l', 'l')
) %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed"),
full_width = TRUE,
position = "center"
) %>%
row_spec(0, bold = TRUE, color = "white", background = "#3498db") %>%
scroll_box(width = "100%", height = "500px")| Variable | Descripción/Significado |
|---|---|
| DEPREG | Departamento de registro |
| MUPREG | Municipio de registro |
| MESREG | Mes de registro |
| AÑOREG | Año de registro |
| DEPOCU | Departamento de ocurrencia |
| MUPOCU | Municipio de ocurrencia |
| AREAG | Área geográfica (1=Urbana, 2=Rural) |
| SEXO | Sexo del fallecido (1=Masculino, 2=Femenino, 9=No especificado) |
| DIAOCU | Día de ocurrencia |
| MESOCU | Mes de ocurrencia |
| AÑOOCU | Año de ocurrencia |
| TIPAR | Tipo de parto |
| CLAPAR | Clasificación del parto |
| VIAPAR | Vía del parto |
| SEMGES | Semanas de gestación |
| EDADM | Edad de la madre (en años) |
| DEPREM | Departamento de residencia de la madre |
| MUPREM | Municipio de residencia de la madre |
| GRETNM | Grupo étnico de la madre |
| ESCIVM | Estado civil de la madre |
| NACIOM | Nacionalidad de la madre |
| OCUPAM | Ocupación de la madre |
| ESCOLAM | Escolaridad de la madre (años de estudio) |
| PAISREM | País de residencia de la madre |
| PUEBLOPM | Pueblo/comunidad indígena de la madre |
| CIUOMAD | Ciudad o municipio de residencia de la madre |
| NACIONM | Nacionalidad de la madre (código) |
| CAUDEF | Causa de defunción (código CIE-10) |
| ASISREC | Asistencia recibida (1=Sí, 2=No) |
| SITIOOCU | Sitio de ocurrencia del parto |
| TOHITE | Total de hijos tenidos |
| TOHINM | Total de hijos nacidos muertos |
| TOHIVI | Total de hijos nacidos vivos |
# Función para clasificar variables
clasificar_variable <- function(variable, nombre_var) {
if(is.character(variable)) {
return("Cualitativa - Nominal")
}
if(is.numeric(variable)) {
valores_unicos <- length(unique(na.omit(variable)))
total_valores <- length(na.omit(variable))
ratio <- valores_unicos / total_valores
variables_discretas <- c("SEXO", "DEPREG", "MUPREG", "MESREG", "DEPOCU",
"MUPOCU", "AREAG", "TIPAR", "CLAPAR", "DEPREM",
"MUPREM", "GRETNM", "ESCIVM", "NACIOM", "OCUPAM",
"ASISREC", "SITIOOCU", "TOHITE", "TOHINM", "TOHIVI",
"VIAPAR", "ESCOLAM", "PAISREM", "PUEBLOPM", "NACIONM",
"DIAOCU", "MESOCU", "AÑOOCU", "AÑOREG")
variables_continuas <- c("EDADM", "SEMGES")
if(nombre_var %in% variables_discretas) {
return("Cuantitativa - Discreta")
} else if(nombre_var %in% variables_continuas) {
return("Cuantitativa - Continua")
} else {
if(ratio < 0.05 || valores_unicos < 50) {
return("Cuantitativa - Discreta")
} else {
return("Cuantitativa - Continua")
}
}
}
return("Otro")
}
# Crear tabla de información de variables
info_variables <- data.frame(
Variable = names(datos),
Tipo_R = sapply(datos, class),
Clasificacion = sapply(names(datos), function(nom) {
clasificar_variable(datos[[nom]], nom)
}),
Valores_Unicos = sapply(datos, function(x) length(unique(na.omit(x)))),
Valores_NA = sapply(datos, function(x) sum(is.na(x))),
Porcentaje_NA = round(sapply(datos, function(x) sum(is.na(x)) / length(x) * 100), 2)
)
# Mostrar tabla con formato mejorado
info_variables %>%
kable(
caption = "Tabla 2: Clasificación y Características de las Variables",
col.names = c("Variable", "Tipo en R", "Clasificación Estadística",
"Valores Únicos", "Valores NA", "% NA"),
align = c('l', 'c', 'l', 'r', 'r', 'r')
) %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE,
position = "center"
) %>%
row_spec(0, bold = TRUE, color = "white", background = "#3498db") %>%
scroll_box(width = "100%", height = "500px")| Variable | Tipo en R | Clasificación Estadística | Valores Únicos | Valores NA | % NA | |
|---|---|---|---|---|---|---|
| DEPREG | DEPREG | numeric | Cuantitativa - Discreta | 22 | 0 | 0.00 |
| MUPREG | MUPREG | integer | Cuantitativa - Discreta | 335 | 0 | 0.00 |
| MESREG | MESREG | numeric | Cuantitativa - Discreta | 12 | 0 | 0.00 |
| AÑOREG | AÑOREG | numeric | Cuantitativa - Discreta | 15 | 0 | 0.00 |
| DEPOCU | DEPOCU | numeric | Cuantitativa - Discreta | 22 | 0 | 0.00 |
| MUPOCU | MUPOCU | integer | Cuantitativa - Discreta | 311 | 0 | 0.00 |
| AREAG | AREAG | numeric | Cuantitativa - Discreta | 3 | 12695 | 30.50 |
| SEXO | SEXO | numeric | Cuantitativa - Discreta | 3 | 0 | 0.00 |
| DIAOCU | DIAOCU | numeric | Cuantitativa - Discreta | 31 | 0 | 0.00 |
| MESOCU | MESOCU | numeric | Cuantitativa - Discreta | 12 | 0 | 0.00 |
| AÑOOCU | AÑOOCU | numeric | Cuantitativa - Discreta | 11 | 9737 | 23.39 |
| TIPAR | TIPAR | numeric | Cuantitativa - Discreta | 4 | 0 | 0.00 |
| CLAPAR | CLAPAR | numeric | Cuantitativa - Discreta | 3 | 0 | 0.00 |
| SEMGES | SEMGES | numeric | Cuantitativa - Continua | 67 | 0 | 0.00 |
| EDADM | EDADM | numeric | Cuantitativa - Continua | 47 | 0 | 0.00 |
| DEPREM | DEPREM | numeric | Cuantitativa - Discreta | 25 | 0 | 0.00 |
| MUPREM | MUPREM | integer | Cuantitativa - Discreta | 341 | 0 | 0.00 |
| GRETNM | GRETNM | numeric | Cuantitativa - Discreta | 3 | 28590 | 68.69 |
| ESCIVM | ESCIVM | numeric | Cuantitativa - Discreta | 4 | 0 | 0.00 |
| NACIOM | NACIOM | numeric | Cuantitativa - Discreta | 18 | 22010 | 52.88 |
| OCUPAM | OCUPAM | numeric | Cuantitativa - Discreta | 72 | 28590 | 68.69 |
| CAUDEF | CAUDEF | character | Cualitativa - Nominal | 206 | 0 | 0.00 |
| ASISREC | ASISREC | numeric | Cuantitativa - Discreta | 6 | 0 | 0.00 |
| SITIOOCU | SITIOOCU | numeric | Cuantitativa - Discreta | 9 | 0 | 0.00 |
| TOHITE | TOHITE | numeric | Cuantitativa - Discreta | 21 | 351 | 0.84 |
| TOHINM | TOHINM | numeric | Cuantitativa - Discreta | 17 | 142 | 0.34 |
| TOHIVI | TOHIVI | numeric | Cuantitativa - Discreta | 19 | 258 | 0.62 |
| VIAPAR | VIAPAR | numeric | Cuantitativa - Discreta | 2 | 3233 | 7.77 |
| ESCOLAM | ESCOLAM | numeric | Cuantitativa - Discreta | 7 | 3233 | 7.77 |
| PAISREM | PAISREM | numeric | Cuantitativa - Discreta | 6 | 9876 | 23.73 |
| PUEBLOPM | PUEBLOPM | numeric | Cuantitativa - Discreta | 6 | 13033 | 31.31 |
| CIUOMAD | CIUOMAD | character | Cualitativa - Nominal | 74 | 0 | 0.00 |
| NACIONM | NACIONM | numeric | Cuantitativa - Discreta | 17 | 19613 | 47.12 |
resumen_tipos <- info_variables %>%
group_by(Clasificacion) %>%
summarise(
Cantidad = n(),
Porcentaje = round(n() / nrow(info_variables) * 100, 1)
)
resumen_tipos %>%
kable(
caption = "Tabla 3: Distribución de Variables por Tipo",
col.names = c("Clasificación", "Cantidad", "Porcentaje (%)"),
align = c('l', 'r', 'r')
) %>%
kable_styling(
bootstrap_options = c("striped", "hover"),
full_width = FALSE,
position = "center"
) %>%
row_spec(0, bold = TRUE, color = "white", background = "#2ecc71")| Clasificación | Cantidad | Porcentaje (%) |
|---|---|---|
| Cualitativa - Nominal | 2 | 6.1 |
| Cuantitativa - Continua | 2 | 6.1 |
| Cuantitativa - Discreta | 29 | 87.9 |
vars_numericas <- names(datos)[sapply(datos, is.numeric)]
resumen_numericas <- data.frame(
Variable = character(),
Media = numeric(),
Mediana = numeric(),
Desv_Est = numeric(),
Min = numeric(),
Max = numeric(),
Q1 = numeric(),
Q3 = numeric(),
Asimetria = numeric(),
Curtosis = numeric(),
stringsAsFactors = FALSE
)
for(var in vars_numericas) {
datos_var <- datos[[var]][!is.na(datos[[var]])]
if(length(datos_var) > 0) {
resumen_numericas <- rbind(resumen_numericas, data.frame(
Variable = var,
Media = mean(datos_var),
Mediana = median(datos_var),
Desv_Est = sd(datos_var),
Min = min(datos_var),
Max = max(datos_var),
Q1 = quantile(datos_var, 0.25),
Q3 = quantile(datos_var, 0.75),
Asimetria = skewness(datos_var),
Curtosis = kurtosis(datos_var)
))
}
}
resumen_numericas %>%
mutate(across(where(is.numeric), ~round(., 2))) %>%
kable(
caption = "Tabla 4: Estadísticas Descriptivas de Variables Numéricas",
align = c('l', rep('r', 9))
) %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed"),
full_width = TRUE,
font_size = 11
) %>%
row_spec(0, bold = TRUE, color = "white", background = "#e74c3c") %>%
scroll_box(width = "100%", height = "400px")| Variable | Media | Mediana | Desv_Est | Min | Max | Q1 | Q3 | Asimetria | Curtosis | |
|---|---|---|---|---|---|---|---|---|---|---|
| 25% | DEPREG | 8.70 | 9 | 6.14 | 1 | 22 | 2 | 14 | 0.16 | 1.76 |
| 25%1 | MUPREG | 874.42 | 901 | 615.18 | 101 | 2217 | 201 | 1415 | 0.16 | 1.75 |
| 25%2 | MESREG | 6.47 | 7 | 3.46 | 1 | 12 | 3 | 9 | -0.02 | 1.78 |
| 25%3 | AÑOREG | 2015.09 | 2015 | 3.94 | 2009 | 2023 | 2012 | 2018 | 0.13 | 1.87 |
| 25%4 | DEPOCU | 8.70 | 9 | 6.14 | 1 | 22 | 2 | 14 | 0.16 | 1.76 |
| 25%5 | MUPOCU | 874.09 | 901 | 615.00 | 101 | 2215 | 201 | 1415 | 0.16 | 1.75 |
| 25%6 | AREAG | 2.03 | 1 | 2.42 | 1 | 9 | 1 | 2 | 2.45 | 7.23 |
| 25%7 | SEXO | 1.51 | 1 | 0.71 | 1 | 9 | 1 | 2 | 5.32 | 56.57 |
| 25%8 | DIAOCU | 15.64 | 16 | 8.76 | 1 | 31 | 8 | 23 | 0.02 | 1.81 |
| 25%9 | MESOCU | 6.50 | 7 | 3.45 | 1 | 12 | 3 | 9 | -0.02 | 1.79 |
| 25%10 | AÑOOCU | 1812.91 | 2016 | 605.96 | 9 | 2022 | 2011 | 2019 | -2.64 | 7.97 |
| 25%11 | TIPAR | 1.45 | 1 | 1.78 | 1 | 9 | 1 | 1 | 3.97 | 16.92 |
| 25%12 | CLAPAR | 1.64 | 1 | 1.77 | 1 | 9 | 1 | 2 | 3.69 | 15.48 |
| 25%13 | SEMGES | 71.30 | 37 | 168.45 | 1 | 999 | 32 | 40 | 5.25 | 28.96 |
| 25%14 | EDADM | 59.42 | 28 | 162.49 | 10 | 999 | 22 | 35 | 5.54 | 32.10 |
| 25%15 | DEPREM | 38.56 | 10 | 456.63 | 1 | 9999 | 4 | 16 | 21.69 | 473.22 |
| 25%16 | MUPREM | 1802.71 | 1020 | 2704.10 | 101 | 9999 | 409 | 1609 | 2.55 | 7.98 |
| 25%17 | GRETNM | 4.18 | 2 | 3.65 | 1 | 9 | 1 | 9 | 0.54 | 1.34 |
| 25%18 | ESCIVM | 1.99 | 1 | 2.02 | 1 | 9 | 1 | 2 | 2.98 | 10.59 |
| 25%19 | NACIOM | 446.38 | 320 | 1202.85 | 31 | 9999 | 320 | 320 | 7.79 | 61.87 |
| 25%20 | OCUPAM | 9393.85 | 9711 | 1498.07 | 1212 | 9999 | 9711 | 9712 | -3.85 | 16.65 |
| 25%21 | ASISREC | 2.08 | 1 | 2.04 | 1 | 9 | 1 | 3 | 2.19 | 7.28 |
| 25%22 | SITIOOCU | 3.39 | 1 | 2.97 | 1 | 9 | 1 | 6 | 0.79 | 2.09 |
| 25%23 | TOHITE | 95.79 | 9 | 217.47 | 0 | 999 | 3 | 99 | 3.72 | 15.63 |
| 25%24 | TOHINM | 106.83 | 1 | 262.41 | 0 | 999 | 1 | 99 | 3.01 | 10.39 |
| 25%25 | TOHIVI | 87.81 | 4 | 218.90 | 0 | 999 | 1 | 99 | 3.74 | 15.74 |
| 25%26 | VIAPAR | 1.23 | 1 | 0.42 | 1 | 2 | 1 | 1 | 1.27 | 2.62 |
| 25%27 | ESCOLAM | 2.67 | 2 | 2.23 | 1 | 9 | 1 | 3 | 1.92 | 5.92 |
| 25%28 | PAISREM | 765.77 | 320 | 2028.72 | 84 | 9999 | 320 | 320 | 4.33 | 19.76 |
| 25%29 | PUEBLOPM | 3.04 | 1 | 2.54 | 1 | 9 | 1 | 4 | 1.19 | 3.58 |
| 25%30 | NACIONM | 551.47 | 320 | 1475.61 | 32 | 9999 | 320 | 320 | 6.24 | 40.01 |
Interpretación de Medidas:
pruebas_normalidad <- data.frame(
Variable = character(),
n = integer(),
Shapiro_W = numeric(),
Shapiro_pvalor = numeric(),
KS_estadistico = numeric(),
KS_pvalor = numeric(),
Es_Normal = character(),
stringsAsFactors = FALSE
)
for(var in vars_numericas) {
datos_var <- datos[[var]][!is.na(datos[[var]])]
n <- length(datos_var)
if(n > 3 && n < 5000) {
shapiro_test <- shapiro.test(datos_var)
ks_test <- ks.test(datos_var, "pnorm", mean(datos_var), sd(datos_var))
es_normal <- ifelse(shapiro_test$p.value > 0.05 && ks_test$p.value > 0.05,
"✓ SÍ", "✗ NO")
pruebas_normalidad <- rbind(pruebas_normalidad, data.frame(
Variable = var,
n = n,
Shapiro_W = shapiro_test$statistic,
Shapiro_pvalor = shapiro_test$p.value,
KS_estadistico = ks_test$statistic,
KS_pvalor = ks_test$p.value,
Es_Normal = es_normal
))
}
}
pruebas_normalidad %>%
mutate(
Shapiro_W = round(Shapiro_W, 4),
Shapiro_pvalor = format.pval(Shapiro_pvalor, digits = 3),
KS_estadistico = round(KS_estadistico, 4),
KS_pvalor = format.pval(KS_pvalor, digits = 3)
) %>%
kable(
caption = "Tabla 5: Pruebas de Normalidad (α = 0.05)",
col.names = c("Variable", "n", "W", "p-valor", "D", "p-valor", "Normal"),
align = c('l', 'r', 'r', 'r', 'r', 'r', 'c')
) %>%
kable_styling(
bootstrap_options = c("striped", "hover"),
full_width = FALSE
) %>%
row_spec(0, bold = TRUE, color = "white", background = "#9b59b6") %>%
add_header_above(c(" " = 2, "Shapiro-Wilk" = 2, "Kolmogorov-Smirnov" = 2, " " = 1)) %>%
scroll_box(width = "100%", height = "400px")| Variable | n | W | p-valor | D | p-valor | Normal |
|---|---|---|---|---|---|---|
| NA | NA | NA | NA | NA | NA | NA |
| :——– | –: | –: | ——-: | –: | ——-: | :——: |
Interpretación:
Si p-valor < 0.05, rechazamos la hipótesis de normalidad. La mayoría de las variables no siguen una distribución normal, lo cual es común en datos de registros administrativos.
vars_clave <- c("EDADM", "SEMGES", "AÑOREG", "MESREG", "SEXO")
vars_graficar <- vars_clave[vars_clave %in% vars_numericas]
par(mfrow = c(2, 3), mar = c(4, 4, 3, 1))
for(var in vars_graficar) {
datos_var <- datos[[var]][!is.na(datos[[var]])]
qqnorm(datos_var, main = paste("Q-Q Plot:", var),
col = "#3498db", pch = 20, cex = 0.5)
qqline(datos_var, col = "#e74c3c", lwd = 2)
}
par(mfrow = c(1, 1))par(mfrow = c(2, 3), mar = c(4, 4, 3, 1))
for(var in vars_graficar) {
datos_var <- datos[[var]][!is.na(datos[[var]])]
hist(datos_var,
probability = TRUE,
main = paste("Histograma:", var),
xlab = var,
col = "#3498db",
border = "white",
las = 1)
curve(dnorm(x, mean = mean(datos_var), sd = sd(datos_var)),
add = TRUE, col = "#e74c3c", lwd = 2)
lines(density(datos_var), col = "#2ecc71", lwd = 2)
legend("topright",
legend = c("Normal teórica", "Densidad real"),
col = c("#e74c3c", "#2ecc71"),
lwd = 2, cex = 0.7, bty = "n")
}
par(mfrow = c(1, 1))identificar_distribucion <- function(asimetria, curtosis) {
if(abs(asimetria) < 0.5 && abs(curtosis - 3) < 0.5) {
return("📊 Aproximadamente Normal")
} else if(asimetria > 1) {
return("📈 Sesgada a la derecha")
} else if(asimetria < -1) {
return("📉 Sesgada a la izquierda")
} else if(curtosis > 4) {
return("🔺 Leptocúrtica")
} else if(curtosis < 2) {
return("🔻 Platicúrtica")
} else {
return("〰️ Asimétrica")
}
}
resumen_numericas$Tipo_Distribucion <- mapply(
identificar_distribucion,
resumen_numericas$Asimetria,
resumen_numericas$Curtosis
)
resumen_numericas %>%
select(Variable, Asimetria, Curtosis, Tipo_Distribucion) %>%
mutate(
Asimetria = round(Asimetria, 2),
Curtosis = round(Curtosis, 2)
) %>%
kable(
caption = "Tabla 6: Clasificación de Distribuciones",
col.names = c("Variable", "Asimetría", "Curtosis", "Tipo de Distribución"),
align = c('l', 'r', 'r', 'l')
) %>%
kable_styling(
bootstrap_options = c("striped", "hover"),
full_width = FALSE
) %>%
row_spec(0, bold = TRUE, color = "white", background = "#f39c12") %>%
scroll_box(width = "100%", height = "400px")| Variable | Asimetría | Curtosis | Tipo de Distribución | |
|---|---|---|---|---|
| 25% | DEPREG | 0.16 | 1.76 | 🔻 Platicúrtica | |
| 25%1 | MUPREG | 0.16 | 1.75 | 🔻 Platicúrtica | |
| 25%2 | MESREG | -0.02 | 1.78 | 🔻 Platicúrtica | |
| 25%3 | AÑOREG | 0.13 | 1.87 | 🔻 Platicúrtica | |
| 25%4 | DEPOCU | 0.16 | 1.76 | 🔻 Platicúrtica | |
| 25%5 | MUPOCU | 0.16 | 1.75 | 🔻 Platicúrtica | |
| 25%6 | AREAG | 2.45 | 7.23 | 📈 Sesgada a la derecha | |
| 25%7 | SEXO | 5.32 | 56.57 | 📈 Sesgada a la derecha | |
| 25%8 | DIAOCU | 0.02 | 1.81 | 🔻 Platicúrtica | |
| 25%9 | MESOCU | -0.02 | 1.79 | 🔻 Platicúrtica | |
| 25%10 | AÑOOCU | -2.64 | 7.97 | 📉 Sesgada a la izquierda | |
| 25%11 | TIPAR | 3.97 | 16.92 | 📈 Sesgada a la derecha | |
| 25%12 | CLAPAR | 3.69 | 15.48 | 📈 Sesgada a la derecha | |
| 25%13 | SEMGES | 5.25 | 28.96 | 📈 Sesgada a la derecha | |
| 25%14 | EDADM | 5.54 | 32.10 | 📈 Sesgada a la derecha | |
| 25%15 | DEPREM | 21.69 | 473.22 | 📈 Sesgada a la derecha | |
| 25%16 | MUPREM | 2.55 | 7.98 | 📈 Sesgada a la derecha | |
| 25%17 | GRETNM | 0.54 | 1.34 | 🔻 Platicúrtica | |
| 25%18 | ESCIVM | 2.98 | 10.59 | 📈 Sesgada a la derecha | |
| 25%19 | NACIOM | 7.79 | 61.87 | 📈 Sesgada a la derecha | |
| 25%20 | OCUPAM | -3.85 | 16.65 | 📉 Sesgada a la izquierda | |
| 25%21 | ASISREC | 2.19 | 7.28 | 📈 Sesgada a la derecha | |
| 25%22 | SITIOOCU | 0.79 | 2.09 | 〰️ Asimétrica |
| 25%23 | TOHITE | 3.72 | 15.63 | 📈 Sesgada a la derecha | |
| 25%24 | TOHINM | 3.01 | 10.39 | 📈 Sesgada a la derecha | |
| 25%25 | TOHIVI | 3.74 | 15.74 | 📈 Sesgada a la derecha | |
| 25%26 | VIAPAR | 1.27 | 2.62 | 📈 Sesgada a la derecha | |
| 25%27 | ESCOLAM | 1.92 | 5.92 | 📈 Sesgada a la derecha | |
| 25%28 | PAISREM | 4.33 | 19.76 | 📈 Sesgada a la derecha | |
| 25%29 | PUEBLOPM | 1.19 | 3.58 | 📈 Sesgada a la derecha | |
| 25%30 | NACIONM | 6.24 | 40.01 | 📈 Sesgada a la derecha | |
vars_categoricas <- c()
for(var in names(datos)) {
if(is.character(datos[[var]])) {
vars_categoricas <- c(vars_categoricas, var)
} else if(is.numeric(datos[[var]])) {
n_unicos <- length(unique(na.omit(datos[[var]])))
if(n_unicos < 20) {
vars_categoricas <- c(vars_categoricas, var)
}
}
}Total de variables categóricas identificadas: 22
Variables: MESREG, AÑOREG, AREAG, SEXO, MESOCU, AÑOOCU, TIPAR, CLAPAR, GRETNM, ESCIVM, …
crear_tabla_frecuencias <- function(variable, nombre_var) {
tabla <- as.data.frame(table(variable, useNA = "ifany"))
colnames(tabla) <- c(nombre_var, "Frecuencia")
tabla$Freq_Relativa <- tabla$Frecuencia / sum(tabla$Frecuencia)
tabla$Porcentaje <- round(tabla$Freq_Relativa * 100, 2)
tabla$Freq_Acumulada <- cumsum(tabla$Frecuencia)
tabla$Porc_Acumulado <- round(cumsum(tabla$Freq_Relativa) * 100, 2)
return(tabla)
}if("SEXO" %in% names(datos)) {
tabla <- crear_tabla_frecuencias(datos$SEXO, "SEXO")
tabla %>%
kable(
caption = "Tabla 7: Distribución de Frecuencias - SEXO",
align = c('c', 'r', 'r', 'r', 'r', 'r')
) %>%
kable_styling(
bootstrap_options = c("striped", "hover"),
full_width = FALSE,
position = "center"
) %>%
row_spec(0, bold = TRUE, color = "white", background = "#3498db")
# Gráfico
ggplot(datos, aes(x = factor(SEXO), fill = factor(SEXO))) +
geom_bar(color = "black") +
geom_text(stat = 'count', aes(label = ..count..), vjust = -0.5, size = 5) +
scale_fill_manual(values = c("#3498db", "#e74c3c", "#95a5a6")) +
labs(
title = "Distribución por Sexo",
x = "Sexo (1=Masculino, 2=Femenino, 9=No especificado)",
y = "Frecuencia"
) +
theme_minimal() +
theme(
legend.position = "none",
plot.title = element_text(hjust = 0.5, face = "bold", size = 14)
)
}if("ASISREC" %in% names(datos)) {
tabla <- crear_tabla_frecuencias(datos$ASISREC, "ASISREC")
tabla %>%
kable(
caption = "Tabla 8: Distribución de Frecuencias - ASISREC (Asistencia Recibida)",
align = c('c', 'r', 'r', 'r', 'r', 'r')
) %>%
kable_styling(
bootstrap_options = c("striped", "hover"),
full_width = FALSE,
position = "center"
) %>%
row_spec(0, bold = TRUE, color = "white", background = "#2ecc71")
}| ASISREC | Frecuencia | Freq_Relativa | Porcentaje | Freq_Acumulada | Porc_Acumulado |
|---|---|---|---|---|---|
| 1 | 28892 | 0.6941355 | 69.41 | 28892 | 69.41 |
| 2 | 661 | 0.0158806 | 1.59 | 29553 | 71.00 |
| 3 | 6129 | 0.1472503 | 14.73 | 35682 | 85.73 |
| 4 | 284 | 0.0068232 | 0.68 | 35966 | 86.41 |
| 5 | 3490 | 0.0838479 | 8.38 | 39456 | 94.79 |
| 9 | 2167 | 0.0520626 | 5.21 | 41623 | 100.00 |
if("SITIOOCU" %in% names(datos)) {
tabla <- crear_tabla_frecuencias(datos$SITIOOCU, "SITIOOCU")
tabla %>%
kable(
caption = "Tabla 9: Distribución de Frecuencias - SITIOOCU (Sitio de Ocurrencia)",
align = c('c', 'r', 'r', 'r', 'r', 'r')
) %>%
kable_styling(
bootstrap_options = c("striped", "hover"),
full_width = FALSE,
position = "center"
) %>%
row_spec(0, bold = TRUE, color = "white", background = "#9b59b6")
}| SITIOOCU | Frecuencia | Freq_Relativa | Porcentaje | Freq_Acumulada | Porc_Acumulado |
|---|---|---|---|---|---|
| 1 | 21784 | 0.5233645 | 52.34 | 21784 | 52.34 |
| 2 | 2335 | 0.0560988 | 5.61 | 24119 | 57.95 |
| 3 | 1074 | 0.0258030 | 2.58 | 25193 | 60.53 |
| 4 | 2229 | 0.0535521 | 5.36 | 27422 | 65.88 |
| 5 | 62 | 0.0014896 | 0.15 | 27484 | 66.03 |
| 6 | 8341 | 0.2003940 | 20.04 | 35825 | 86.07 |
| 7 | 18 | 0.0004325 | 0.04 | 35843 | 86.11 |
| 8 | 76 | 0.0018259 | 0.18 | 35919 | 86.30 |
| 9 | 5704 | 0.1370396 | 13.70 | 41623 | 100.00 |
if("CAUDEF" %in% names(datos)) {
tabla <- crear_tabla_frecuencias(datos$CAUDEF, "CAUDEF")
# Mostrar top 20
tabla_top20 <- head(tabla[order(-tabla$Frecuencia), ], 20)
tabla_top20 %>%
kable(
caption = "Tabla 10: Top 20 Causas de Defunción más Frecuentes",
align = c('l', 'r', 'r', 'r', 'r', 'r')
) %>%
kable_styling(
bootstrap_options = c("striped", "hover"),
full_width = FALSE,
position = "center"
) %>%
row_spec(0, bold = TRUE, color = "white", background = "#e74c3c") %>%
scroll_box(width = "100%", height = "500px")
# Gráfico Top 15
top15 <- head(tabla[order(-tabla$Frecuencia), ], 15)
ggplot(top15, aes(x = reorder(CAUDEF, Frecuencia), y = Frecuencia)) +
geom_bar(stat = "identity", fill = "#e74c3c", color = "black") +
coord_flip() +
geom_text(aes(label = Frecuencia), hjust = -0.2, size = 3.5) +
labs(
title = "Top 15 Causas de Defunción",
x = "Código de Causa",
y = "Frecuencia"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
axis.text.y = element_text(size = 10)
)
}A continuación se presentan gráficos exploratorios que permiten visualizar el estado general de los datos, identificar patrones, valores atípicos y distribuciones antes de profundizar en relaciones entre variables.
vars_boxplot <- c("EDADM", "SEMGES", "TOHITE", "TOHINM", "TOHIVI")
vars_boxplot <- vars_boxplot[vars_boxplot %in% names(datos)]
if(length(vars_boxplot) > 0) {
datos_long <- datos %>%
select(all_of(vars_boxplot)) %>%
pivot_longer(cols = everything(), names_to = "Variable", values_to = "Valor") %>%
filter(!is.na(Valor), Valor < 900)
ggplot(datos_long, aes(x = Variable, y = Valor, fill = Variable)) +
geom_boxplot(outlier.color = "#e74c3c", outlier.alpha = 0.3, outlier.size = 0.8) +
stat_summary(fun = mean, geom = "point", shape = 18, size = 3, color = "black") +
scale_fill_brewer(palette = "Set2") +
labs(
title = "Boxplots de Variables Numéricas Clave",
subtitle = "Se excluyen códigos especiales (≥900). El diamante negro indica la media.",
x = NULL, y = "Valor"
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(hjust = 0.5, face = "bold"),
plot.subtitle = element_text(hjust = 0.5, size = 10, color = "gray40"),
legend.position = "none"
)
}vars_densidad <- c("EDADM", "SEMGES")
vars_densidad <- vars_densidad[vars_densidad %in% names(datos)]
if(length(vars_densidad) > 0) {
plots_densidad <- list()
for(v in vars_densidad) {
datos_filtrados <- datos %>%
filter(!is.na(.data[[v]]), .data[[v]] < 900)
p <- ggplot(datos_filtrados, aes(x = .data[[v]])) +
geom_histogram(aes(y = after_stat(density)), bins = 40,
fill = "#3498db", color = "white", alpha = 0.6) +
geom_density(color = "#e74c3c", linewidth = 1.2) +
geom_vline(aes(xintercept = mean(.data[[v]], na.rm = TRUE)),
color = "#2c3e50", linetype = "dashed", linewidth = 0.8) +
geom_vline(aes(xintercept = median(.data[[v]], na.rm = TRUE)),
color = "#27ae60", linetype = "dotted", linewidth = 0.8) +
labs(
title = paste("Distribución de", v),
subtitle = "Línea punteada = mediana | Línea discontinua = media",
x = v, y = "Densidad"
) +
theme_minimal(base_size = 12) +
theme(plot.title = element_text(hjust = 0.5, face = "bold"),
plot.subtitle = element_text(hjust = 0.5, size = 9, color = "gray40"))
plots_densidad[[v]] <- p
}
do.call(grid.arrange, c(plots_densidad, ncol = length(plots_densidad)))
}if("SEXO" %in% names(datos)) {
datos_sexo <- datos %>%
filter(!is.na(SEXO)) %>%
mutate(SEXO_label = case_when(
SEXO == 1 ~ "Masculino",
SEXO == 2 ~ "Femenino",
SEXO == 9 ~ "No especificado",
TRUE ~ as.character(SEXO)
)) %>%
count(SEXO_label) %>%
mutate(porcentaje = round(n / sum(n) * 100, 1))
ggplot(datos_sexo, aes(x = reorder(SEXO_label, -n), y = n, fill = SEXO_label)) +
geom_col(width = 0.6, show.legend = FALSE) +
geom_text(aes(label = paste0(format(n, big.mark = ","), "\n(", porcentaje, "%)")),
vjust = -0.3, size = 4, fontface = "bold") +
scale_fill_manual(values = c("Masculino" = "#3498db", "Femenino" = "#e91e63",
"No especificado" = "#95a5a6")) +
labs(title = "Distribución por Sexo", x = NULL, y = "Frecuencia") +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(hjust = 0.5, face = "bold")) +
scale_y_continuous(expand = expansion(mult = c(0, 0.15)))
}if("AREAG" %in% names(datos)) {
datos_area <- datos %>%
filter(!is.na(AREAG)) %>%
mutate(AREAG_label = case_when(
AREAG == 1 ~ "Urbana",
AREAG == 2 ~ "Rural",
TRUE ~ as.character(AREAG)
)) %>%
count(AREAG_label) %>%
mutate(porcentaje = round(n / sum(n) * 100, 1))
ggplot(datos_area, aes(x = "", y = n, fill = AREAG_label)) +
geom_col(width = 1) +
coord_polar(theta = "y") +
geom_text(aes(label = paste0(AREAG_label, "\n", porcentaje, "%")),
position = position_stack(vjust = 0.5), size = 5, fontface = "bold") +
scale_fill_manual(values = c("Urbana" = "#2ecc71", "Rural" = "#f39c12")) +
labs(title = "Distribución por Área Geográfica", fill = "Área") +
theme_void(base_size = 13) +
theme(plot.title = element_text(hjust = 0.5, face = "bold"))
}if("ASISREC" %in% names(datos)) {
datos_asis <- datos %>%
filter(!is.na(ASISREC)) %>%
mutate(ASISREC_label = case_when(
ASISREC == 1 ~ "Sí recibió",
ASISREC == 2 ~ "No recibió",
TRUE ~ as.character(ASISREC)
)) %>%
count(ASISREC_label) %>%
mutate(porcentaje = round(n / sum(n) * 100, 1))
ggplot(datos_asis, aes(x = reorder(ASISREC_label, -n), y = n, fill = ASISREC_label)) +
geom_col(width = 0.5, show.legend = FALSE) +
geom_text(aes(label = paste0(format(n, big.mark = ","), "\n(", porcentaje, "%)")),
vjust = -0.3, size = 4, fontface = "bold") +
scale_fill_manual(values = c("Sí recibió" = "#27ae60", "No recibió" = "#c0392b")) +
labs(title = "Asistencia Recibida durante el Parto", x = NULL, y = "Frecuencia") +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(hjust = 0.5, face = "bold")) +
scale_y_continuous(expand = expansion(mult = c(0, 0.15)))
}if("AÑOREG" %in% names(datos)) {
registros_anio <- datos %>%
filter(!is.na(AÑOREG)) %>%
count(AÑOREG)
ggplot(registros_anio, aes(x = AÑOREG, y = n)) +
geom_line(color = "#2c3e50", linewidth = 1) +
geom_point(color = "#e74c3c", size = 3) +
geom_area(alpha = 0.15, fill = "#3498db") +
geom_text(aes(label = format(n, big.mark = ",")), vjust = -1, size = 3.2) +
labs(
title = "Evolución del Número de Registros por Año",
x = "Año de Registro", y = "Cantidad de Registros"
) +
scale_x_continuous(breaks = seq(min(registros_anio$AÑOREG), max(registros_anio$AÑOREG), 1)) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(hjust = 0.5, face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1)
) +
scale_y_continuous(expand = expansion(mult = c(0, 0.12)))
}if("MESOCU" %in% names(datos)) {
meses_nombres <- c("Ene", "Feb", "Mar", "Abr", "May", "Jun",
"Jul", "Ago", "Sep", "Oct", "Nov", "Dic")
registros_mes <- datos %>%
filter(!is.na(MESOCU), MESOCU >= 1, MESOCU <= 12) %>%
count(MESOCU) %>%
mutate(Mes = factor(meses_nombres[MESOCU], levels = meses_nombres))
ggplot(registros_mes, aes(x = Mes, y = n, fill = n)) +
geom_col(show.legend = FALSE) +
scale_fill_gradient(low = "#85c1e9", high = "#1a5276") +
geom_text(aes(label = format(n, big.mark = ",")), vjust = -0.3, size = 3.5) +
labs(
title = "Distribución de Ocurrencias por Mes",
x = "Mes de Ocurrencia", y = "Frecuencia"
) +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(hjust = 0.5, face = "bold")) +
scale_y_continuous(expand = expansion(mult = c(0, 0.1)))
}vars_revision <- c("EDADM", "SEMGES", "TOHITE", "TOHINM", "TOHIVI", "ESCOLAM")
vars_revision <- vars_revision[vars_revision %in% names(datos)]
if(length(vars_revision) > 0) {
resumen_atipicos <- data.frame(
Variable = character(),
N_total = integer(),
N_NA = integer(),
Porc_NA = numeric(),
N_codigo_999 = integer(),
Porc_999 = numeric(),
stringsAsFactors = FALSE
)
for(v in vars_revision) {
vals <- datos[[v]]
n_total <- length(vals)
n_na <- sum(is.na(vals))
n_999 <- sum(vals >= 99 & !is.na(vals))
resumen_atipicos <- rbind(resumen_atipicos, data.frame(
Variable = v,
N_total = n_total,
N_NA = n_na,
Porc_NA = round(n_na / n_total * 100, 2),
N_codigo_999 = n_999,
Porc_999 = round(n_999 / n_total * 100, 2)
))
}
resumen_atipicos %>%
kable(
caption = "Detección de Valores Atípicos y Códigos Especiales",
col.names = c("Variable", "N Total", "N Faltantes (NA)", "% NA",
"N Códigos ≥99", "% Códigos ≥99"),
align = c('l', rep('r', 5))
) %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE
) %>%
row_spec(0, bold = TRUE, color = "white", background = "#8e44ad")
}| Variable | N Total | N Faltantes (NA) | % NA | N Códigos ≥99 | % Códigos ≥99 |
|---|---|---|---|---|---|
| EDADM | 41623 | 0 | 0.00 | 3429 | 8.24 |
| SEMGES | 41623 | 0 | 0.00 | 5531 | 13.29 |
| TOHITE | 41623 | 351 | 0.84 | 19353 | 46.50 |
| TOHINM | 41623 | 142 | 0.34 | 15159 | 36.42 |
| TOHIVI | 41623 | 258 | 0.62 | 16343 | 39.26 |
| ESCOLAM | 41623 | 3233 | 7.77 | 0 | 0.00 |
vars_heatmap <- names(datos)[sapply(datos, is.numeric)]
porc_faltantes <- sapply(datos[vars_heatmap], function(x) {
na_real <- sum(is.na(x))
cod_especial <- sum(x %in% c(99, 999, 9999) & !is.na(x))
round((na_real + cod_especial) / length(x) * 100, 1)
})
df_faltantes <- data.frame(
Variable = names(porc_faltantes),
Porcentaje = as.numeric(porc_faltantes)
) %>%
arrange(desc(Porcentaje))
ggplot(df_faltantes, aes(x = reorder(Variable, Porcentaje), y = Porcentaje, fill = Porcentaje)) +
geom_col() +
coord_flip() +
scale_fill_gradient(low = "#27ae60", high = "#e74c3c", name = "% Datos\nProblema") +
geom_text(aes(label = paste0(Porcentaje, "%")), hjust = -0.1, size = 3.5) +
labs(
title = "Porcentaje de Datos Faltantes o con Códigos Especiales por Variable",
subtitle = "Incluye NA y códigos como 99, 999, 9999",
x = NULL, y = "Porcentaje (%)"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(hjust = 0.5, face = "bold"),
plot.subtitle = element_text(hjust = 0.5, size = 10, color = "gray40")
) +
scale_y_continuous(expand = expansion(mult = c(0, 0.12)))Observaciones de los Gráficos Exploratorios:
# Seleccionar variables numéricas continuas clave para correlación
vars_correlacion <- c("AÑOREG", "MESREG", "EDADM", "SEMGES",
"TOHITE", "TOHINM", "TOHIVI", "ESCOLAM")
# Filtrar solo las que existen en el dataset
vars_correlacion <- vars_correlacion[vars_correlacion %in% names(datos)]
# Crear subset sin NAs
datos_corr <- datos[, vars_correlacion]
datos_corr <- na.omit(datos_corr)
# Calcular matriz de correlación
matriz_correlacion <- cor(datos_corr)
# Mostrar matriz en tabla
matriz_correlacion %>%
round(3) %>%
kable(
caption = "Tabla 11: Matriz de Correlación de Pearson",
align = 'c'
) %>%
kable_styling(
bootstrap_options = c("striped", "hover"),
full_width = FALSE,
font_size = 11
) %>%
row_spec(0, bold = TRUE, color = "white", background = "#e74c3c")| AÑOREG | MESREG | EDADM | SEMGES | TOHITE | TOHINM | TOHIVI | ESCOLAM | |
|---|---|---|---|---|---|---|---|---|
| AÑOREG | 1.000 | -0.006 | -0.048 | -0.224 | 0.077 | 0.358 | 0.222 | -0.025 |
| MESREG | -0.006 | 1.000 | -0.015 | -0.020 | -0.010 | -0.004 | -0.004 | -0.009 |
| EDADM | -0.048 | -0.015 | 1.000 | -0.011 | 0.070 | 0.050 | 0.088 | 0.171 |
| SEMGES | -0.224 | -0.020 | -0.011 | 1.000 | -0.059 | -0.107 | -0.087 | -0.068 |
| TOHITE | 0.077 | -0.010 | 0.070 | -0.059 | 1.000 | 0.743 | 0.846 | 0.176 |
| TOHINM | 0.358 | -0.004 | 0.050 | -0.107 | 0.743 | 1.000 | 0.599 | 0.110 |
| TOHIVI | 0.222 | -0.004 | 0.088 | -0.087 | 0.846 | 0.599 | 1.000 | 0.166 |
| ESCOLAM | -0.025 | -0.009 | 0.171 | -0.068 | 0.176 | 0.110 | 0.166 | 1.000 |
# Visualizar matriz de correlación
corrplot(matriz_correlacion,
method = "color",
type = "upper",
addCoef.col = "black",
number.cex = 0.7,
tl.col = "black",
tl.srt = 45,
title = "Matriz de Correlación",
mar = c(0, 0, 2, 0))# Identificar correlaciones significativas (|r| > 0.3)
correlaciones_significativas <- data.frame()
for(i in 1:(ncol(matriz_correlacion)-1)) {
for(j in (i+1):ncol(matriz_correlacion)) {
cor_valor <- matriz_correlacion[i, j]
if(abs(cor_valor) > 0.3) {
correlaciones_significativas <- rbind(
correlaciones_significativas,
data.frame(
Variable_1 = rownames(matriz_correlacion)[i],
Variable_2 = colnames(matriz_correlacion)[j],
Correlacion = cor_valor,
Fuerza = ifelse(abs(cor_valor) > 0.7, "Fuerte",
ifelse(abs(cor_valor) > 0.5, "Moderada", "Débil")),
Direccion = ifelse(cor_valor > 0, "Positiva", "Negativa")
)
)
}
}
}
# Ordenar por valor absoluto de correlación
if(nrow(correlaciones_significativas) > 0) {
correlaciones_significativas <- correlaciones_significativas[
order(-abs(correlaciones_significativas$Correlacion)),
]
correlaciones_significativas %>%
mutate(Correlacion = round(Correlacion, 3)) %>%
kable(
caption = "Tabla 12: Correlaciones Significativas (|r| > 0.3)",
col.names = c("Variable 1", "Variable 2", "r", "Fuerza", "Dirección"),
align = c('l', 'l', 'r', 'c', 'c')
) %>%
kable_styling(
bootstrap_options = c("striped", "hover"),
full_width = FALSE
) %>%
row_spec(0, bold = TRUE, color = "white", background = "#2ecc71")
} else {
cat("No se encontraron correlaciones significativas (|r| > 0.3)\n")
}| Variable 1 | Variable 2 | r | Fuerza | Dirección | |
|---|---|---|---|---|---|
| 3 | TOHITE | TOHIVI | 0.846 | Fuerte | Positiva |
| 2 | TOHITE | TOHINM | 0.743 | Fuerte | Positiva |
| 4 | TOHINM | TOHIVI | 0.599 | Moderada | Positiva |
| 1 | AÑOREG | TOHINM | 0.358 | Débil | Positiva |
if("EDADM" %in% names(datos) && "SEMGES" %in% names(datos)) {
ggplot(datos %>% filter(EDADM < 100, SEMGES < 100),
aes(x = EDADM, y = SEMGES)) +
geom_point(alpha = 0.3, color = "#3498db") +
geom_smooth(method = "lm", color = "#e74c3c", se = TRUE) +
labs(
title = "Relación: Edad de la Madre vs Semanas de Gestación",
x = "Edad de la Madre (años)",
y = "Semanas de Gestación"
) +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, face = "bold"))
}if("EDADM" %in% names(datos) && "TOHITE" %in% names(datos)) {
ggplot(datos %>% filter(EDADM < 100, TOHITE < 50),
aes(x = EDADM, y = TOHITE)) +
geom_point(alpha = 0.3, color = "#2ecc71") +
geom_smooth(method = "lm", color = "#e74c3c", se = TRUE) +
labs(
title = "Relación: Edad de la Madre vs Total de Hijos Tenidos",
x = "Edad de la Madre (años)",
y = "Total de Hijos Tenidos"
) +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, face = "bold"))
}if("SEMGES" %in% names(datos) && "TOHIVI" %in% names(datos)) {
ggplot(datos %>% filter(SEMGES < 100, TOHIVI < 50),
aes(x = SEMGES, y = TOHIVI)) +
geom_point(alpha = 0.3, color = "#9b59b6") +
geom_smooth(method = "lm", color = "#e74c3c", se = TRUE) +
labs(
title = "Relación: Semanas de Gestación vs Total de Hijos Vivos",
x = "Semanas de Gestación",
y = "Total de Hijos Vivos"
) +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, face = "bold"))
}if("SEXO" %in% names(datos) && "ASISREC" %in% names(datos)) {
# Crear tabla
tabla_sexo_asis <- table(datos$SEXO, datos$ASISREC)
# Mostrar tabla con totales
addmargins(tabla_sexo_asis) %>%
kable(
caption = "Tabla 13: Tabla de Contingencia - SEXO vs ASISREC"
) %>%
kable_styling(
bootstrap_options = c("striped", "hover"),
full_width = FALSE
) %>%
row_spec(0, bold = TRUE, color = "white", background = "#3498db")
# Proporciones por fila (%) - CORRECCIÓN AQUÍ
cat("\n\nProporciones por fila (%):\n")
(prop.table(tabla_sexo_asis, 1) * 100) %>%
round(2) %>%
kable(caption = "Porcentajes por fila") %>%
kable_styling(bootstrap_options = c("striped", "hover")) %>%
print()
# Test de independencia Chi-cuadrado
test_chi <- chisq.test(tabla_sexo_asis)
cat("\n\n**Test de Independencia Chi-cuadrado:**\n")
cat("- Estadístico χ²:", round(test_chi$statistic, 4), "\n")
cat("- p-valor:", format.pval(test_chi$p.value, digits = 4), "\n")
if(test_chi$p.value < 0.05) {
cat("\n**Conclusión:** Las variables NO son independientes (p < 0.05)\n")
cat("Existe una relación estadísticamente significativa entre SEXO y ASISREC\n")
} else {
cat("\n**Conclusión:** Las variables son independientes (p >= 0.05)\n")
cat("No hay evidencia de relación entre SEXO y ASISREC\n")
}
}##
##
## Proporciones por fila (%):
## <table class="table table-striped table-hover" style="margin-left: auto; margin-right: auto;">
## <caption>Porcentajes por fila</caption>
## <thead>
## <tr>
## <th style="text-align:left;"> </th>
## <th style="text-align:right;"> 1 </th>
## <th style="text-align:right;"> 2 </th>
## <th style="text-align:right;"> 3 </th>
## <th style="text-align:right;"> 4 </th>
## <th style="text-align:right;"> 5 </th>
## <th style="text-align:right;"> 9 </th>
## </tr>
## </thead>
## <tbody>
## <tr>
## <td style="text-align:left;"> 1 </td>
## <td style="text-align:right;"> 68.75 </td>
## <td style="text-align:right;"> 1.57 </td>
## <td style="text-align:right;"> 15.22 </td>
## <td style="text-align:right;"> 0.69 </td>
## <td style="text-align:right;"> 8.51 </td>
## <td style="text-align:right;"> 5.26 </td>
## </tr>
## <tr>
## <td style="text-align:left;"> 2 </td>
## <td style="text-align:right;"> 70.18 </td>
## <td style="text-align:right;"> 1.62 </td>
## <td style="text-align:right;"> 14.30 </td>
## <td style="text-align:right;"> 0.68 </td>
## <td style="text-align:right;"> 8.06 </td>
## <td style="text-align:right;"> 5.16 </td>
## </tr>
## <tr>
## <td style="text-align:left;"> 9 </td>
## <td style="text-align:right;"> 67.54 </td>
## <td style="text-align:right;"> 0.52 </td>
## <td style="text-align:right;"> 1.57 </td>
## <td style="text-align:right;"> 0.00 </td>
## <td style="text-align:right;"> 26.18 </td>
## <td style="text-align:right;"> 4.19 </td>
## </tr>
## </tbody>
## </table>
##
##
## **Test de Independencia Chi-cuadrado:**
## - Estadístico χ²: 110.0828
## - p-valor: < 2.2e-16
##
## **Conclusión:** Las variables NO son independientes (p < 0.05)
## Existe una relación estadísticamente significativa entre SEXO y ASISREC
if("SEXO" %in% names(datos) && "SITIOOCU" %in% names(datos)) {
tabla_sexo_sitio <- table(datos$SEXO, datos$SITIOOCU)
addmargins(tabla_sexo_sitio) %>%
kable(
caption = "Tabla 14: Tabla de Contingencia - SEXO vs SITIOOCU"
) %>%
kable_styling(
bootstrap_options = c("striped", "hover"),
full_width = FALSE
) %>%
row_spec(0, bold = TRUE, color = "white", background = "#2ecc71")
# Test Chi-cuadrado
test_chi2 <- chisq.test(tabla_sexo_sitio)
cat("\n**Chi-cuadrado p-valor:**", format.pval(test_chi2$p.value, digits = 4), "\n")
}##
## **Chi-cuadrado p-valor:** < 2.2e-16
if("AREAG" %in% names(datos) && "ASISREC" %in% names(datos)) {
tabla_area_asis <- table(datos$AREAG, datos$ASISREC)
addmargins(tabla_area_asis) %>%
kable(
caption = "Tabla 15: Tabla de Contingencia - AREAG vs ASISREC"
) %>%
kable_styling(
bootstrap_options = c("striped", "hover"),
full_width = FALSE
) %>%
row_spec(0, bold = TRUE, color = "white", background = "#9b59b6")
# Test Chi-cuadrado
test_chi3 <- chisq.test(tabla_area_asis)
cat("\n**Chi-cuadrado p-valor:**", format.pval(test_chi3$p.value, digits = 4), "\n")
if(test_chi3$p.value < 0.05) {
cat("\n**Conclusión:** El área geográfica SÍ influye en la asistencia recibida (p < 0.05)\n")
} else {
cat("\n**Conclusión:** El área geográfica NO influye significativamente en la asistencia (p >= 0.05)\n")
}
}##
## **Chi-cuadrado p-valor:** < 2.2e-16
##
## **Conclusión:** El área geográfica SÍ influye en la asistencia recibida (p < 0.05)
if("SEXO" %in% names(datos) && "ASISREC" %in% names(datos)) {
datos_graf <- datos %>%
filter(!is.na(SEXO) & !is.na(ASISREC) & SEXO %in% c(1, 2)) %>%
mutate(
Sexo = factor(SEXO, levels = c(1, 2),
labels = c("Masculino", "Femenino")),
Asistencia = factor(ASISREC, levels = c(1, 2),
labels = c("Sí recibió", "No recibió"))
) %>%
group_by(Sexo, Asistencia) %>%
summarise(Frecuencia = n(), .groups = "drop")
ggplot(datos_graf, aes(x = Sexo, y = Frecuencia, fill = Asistencia)) +
geom_bar(stat = "identity", position = "dodge", color = "black") +
geom_text(aes(label = Frecuencia),
position = position_dodge(width = 0.9),
vjust = -0.5, size = 3.5) +
scale_fill_manual(values = c("#2ecc71", "#e74c3c")) +
labs(
title = "Asistencia Recibida por Sexo",
x = "Sexo",
y = "Frecuencia",
fill = "Asistencia"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
legend.position = "top"
)
}# Boxplot: Edad de la Madre por Sexo del bebé
if("EDADM" %in% names(datos) && "SEXO" %in% names(datos)) {
datos_box <- datos %>%
filter(EDADM < 100 & SEXO %in% c(1, 2)) %>%
mutate(Sexo = factor(SEXO, levels = c(1, 2),
labels = c("Masculino", "Femenino")))
ggplot(datos_box, aes(x = Sexo, y = EDADM, fill = Sexo)) +
geom_boxplot(alpha = 0.7) +
scale_fill_manual(values = c("#3498db", "#e74c3c")) +
labs(
title = "Distribución de Edad de la Madre por Sexo del Bebé",
x = "Sexo del Bebé",
y = "Edad de la Madre (años)"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold"),
legend.position = "none"
)
}if("AÑOREG" %in% names(datos)) {
tendencia_anual <- datos %>%
group_by(AÑOREG) %>%
summarise(
Total_Registros = n(),
Edad_Promedio = mean(EDADM, na.rm = TRUE),
Semanas_Promedio = mean(SEMGES, na.rm = TRUE)
) %>%
filter(AÑOREG >= 2009 & AÑOREG <= 2023)
# Gráfico de tendencia
ggplot(tendencia_anual, aes(x = AÑOREG, y = Total_Registros)) +
geom_line(color = "#3498db", size = 1.2) +
geom_point(color = "#e74c3c", size = 3) +
labs(
title = "Tendencia de Registros por Año",
x = "Año",
y = "Número de Registros"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1)
) +
scale_x_continuous(breaks = seq(2009, 2023, 1))
}## ========================================
## RESUMEN DE RELACIONES ENTRE VARIABLES
## ========================================
## **CORRELACIONES:**
## --------------
if(exists("correlaciones_significativas") && nrow(correlaciones_significativas) > 0) {
cat("✓ Se encontraron", nrow(correlaciones_significativas),
"correlaciones significativas (|r| > 0.3)\n")
cat(" - Correlación más fuerte: r =",
round(max(abs(correlaciones_significativas$Correlacion)), 3), "\n\n")
} else {
cat("✗ No se encontraron correlaciones fuertes entre variables numéricas\n\n")
}## ✓ Se encontraron 4 correlaciones significativas (|r| > 0.3)
## - Correlación más fuerte: r = 0.846
## **ASOCIACIONES CATEGÓRICAS:**
## -------------------------
## ✓ Se analizaron múltiples tablas de contingencia
## ✓ Se aplicaron pruebas Chi-cuadrado para independencia
## **HALLAZGOS PRINCIPALES:**
## ----------------------
## 1. Relación entre edad de la madre y total de hijos tenidos
## 2. Posible influencia del área geográfica en la asistencia recibida
## 3. Tendencia temporal observable en el número de registros
## 4. Distribución relativamente equilibrada entre sexos
A continuación se plantean cinco hipótesis preliminares basadas en creencias intuitivas sobre el fenómeno estudiado. Cada una será validada o refutada mediante análisis estadístico y visualización.
Las madres que viven en área rural reciben menos asistencia durante el parto que las que viven en área urbana.
# Tabla de contingencia
tabla_area_asis <- table(datos$AREAG, datos$ASISREC)
# Proporciones por fila
prop_area_asis <- prop.table(tabla_area_asis, 1) * 100
kable(round(prop_area_asis,2),
caption = "Porcentaje de Asistencia por Área Geográfica")| 1 | 2 | 3 | 4 | 5 | 9 | |
|---|---|---|---|---|---|---|
| 1 | 92.51 | 0.42 | 2.20 | 0.17 | 2.17 | 2.53 |
| 2 | 3.30 | 0.90 | 72.34 | 2.65 | 17.71 | 3.10 |
| 9 | 27.68 | 12.25 | 2.13 | 1.02 | 8.42 | 48.51 |
##
## Pearson's Chi-squared test
##
## data: tabla_area_asis
## X-squared = 31911, df = 10, p-value < 2.2e-16
Las madres de mayor edad tienden a tener más hijos.
##
## Pearson's product-moment correlation
##
## data: datos$EDADM and datos$TOHITE
## t = 14.602, df = 41270, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## 0.06208668 0.08128286
## sample estimates:
## cor
## 0.07169141
ggplot(datos %>% filter(EDADM < 60, TOHITE < 20),
aes(x = EDADM, y = TOHITE)) +
geom_point(alpha = 0.3) +
geom_smooth(method = "lm", color = "red") +
theme_minimal() +
labs(title = "Edad vs Total de Hijos")Existe estacionalidad en las ocurrencias (algunos meses concentran más casos).
registros_mes <- datos %>%
filter(MESOCU >=1 & MESOCU <=12) %>%
count(MESOCU)
ggplot(registros_mes, aes(x = MESOCU, y = n)) +
geom_col(fill = "steelblue") +
theme_minimal() +
labs(title = "Distribución mensual de ocurrencias")Las madres con menor nivel educativo tienen más hijos.
##
## Pearson's product-moment correlation
##
## data: datos$ESCOLAM and datos$TOHITE
## t = 34.925, df = 38037, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## 0.1665179 0.1859921
## sample estimates:
## cor
## 0.1762722
ggplot(datos %>% filter(ESCOLAM < 20, TOHITE < 20),
aes(x = ESCOLAM, y = TOHITE)) +
geom_point(alpha = 0.3) +
geom_smooth(method = "lm", color = "red") +
theme_minimal() +
labs(title = "Escolaridad vs Total de Hijos")El sitio de ocurrencia influye en la asistencia recibida.
##
## Pearson's Chi-squared test
##
## data: tabla_sitio_asis
## X-squared = 56621, df = 40, p-value < 2.2e-16
El objetivo del clustering es identificar grupos homogéneos de registros según características similares.
Usaremos variables numéricas relevantes:
EDADM (edad madre)
SEMGES (semanas gestación)
TOHITE (total hijos)
ESCOLAM (escolaridad)
library(cluster)
datos_cluster <- datos %>%
select(EDADM, SEMGES, TOHITE, ESCOLAM) %>%
filter(
EDADM < 60,
SEMGES < 50,
TOHITE < 20,
ESCOLAM < 20
) %>%
na.omit()
# Estandarización
datos_scaled <- scale(datos_cluster)
wss <- numeric(10)
for(i in 1:10){
wss[i] <- sum(kmeans(datos_scaled, centers=i, nstart=10)$withinss)
}
plot(1:10, wss, type="b",
xlab="Número de clusters",
ylab="Suma de cuadrados intra-grupo")set.seed(123)
k3 <- kmeans(datos_scaled, centers=3, nstart=25)
datos_cluster$cluster <- factor(k3$cluster)
ggplot(datos_cluster, aes(x=EDADM, y=TOHITE, color=cluster)) +
geom_point(alpha=0.6) +
theme_minimal() +
labs(title="Clusters según Edad y Número de Hijos")El método del codo indicó que el número óptimo de grupos es k = 3, ya que a partir de este punto la reducción en la suma de cuadrados intra-grupo se estabiliza, indicando rendimientos decrecientes al aumentar el número de clusters.
El análisis de medias permitió identificar tres perfiles diferenciados:
Cluster 1 (Perfil intermedio educado): Madres con edad promedio de 29 años, nivel educativo medio (≈9 años) y número moderado de hijos (≈3.8). Representa un grupo con características intermedias tanto en edad como en fecundidad.
Cluster 2 (Perfil joven con baja escolaridad): Grupo más joven (≈26 años), con bajo nivel educativo (≈2 años) y menor número de hijos (≈2.7). Puede representar madres en etapa inicial reproductiva y en situación de vulnerabilidad educativa.
Cluster 3 (Perfil de mayor edad y alta fecundidad): Madres de mayor edad (≈36 años), con el mayor número promedio de hijos (≈6.3) y el nivel educativo más bajo (≈1.5 años). Este grupo refleja un patrón de alta fecundidad asociado a baja escolaridad.
Los resultados sugieren una relación estructural entre edad, escolaridad y número de hijos, donde niveles educativos más bajos se asocian con mayor fecundidad. El clustering permitió identificar perfiles poblacionales claramente diferenciados, lo cual puede ser relevante para el diseño de políticas públicas focalizadas.
A lo largo del análisis exploratorio se aplicaron diversas operaciones de limpieza y filtrado para garantizar la calidad y coherencia de los resultados. A continuación se documenta cada una de ellas de forma estructurada.
operaciones_limpieza <- data.frame(
No = 1:10,
Operacion = c(
"Eliminación de valores NA (na.omit / !is.na)",
"Exclusión de códigos especiales ≥ 900",
"Filtro de edad de la madre (EDADM < 100)",
"Filtro de semanas de gestación (SEMGES < 100)",
"Filtro de total hijos tenidos (TOHITE < 50)",
"Filtro de total hijos vivos (TOHIVI < 50)",
"Validación de meses (MESOCU entre 1 y 12)",
"Exclusión de sexo no especificado (SEXO ∈ {1, 2})",
"Acotamiento del rango temporal (2009-2023)",
"Identificación de códigos 99, 999, 9999 como datos faltantes"
),
Justificacion = c(
"Los registros con valores faltantes (NA) fueron excluidos en cálculos estadísticos, gráficos y tablas de frecuencia para evitar distorsiones en medias, medianas, correlaciones y pruebas de normalidad.",
"Variables como EDADM, SEMGES, TOHITE, TOHINM y TOHIVI utilizan códigos numéricos altos (≥ 900) para representar información no disponible. Estos valores fueron excluidos en boxplots y gráficos de densidad para que las distribuciones reflejen solo datos reales.",
"Se excluyeron registros con EDADM ≥ 100 ya que estos valores corresponden a códigos de datos faltantes (99, 999) y no a edades reales. La edad máxima biológicamente plausible para una madre es menor a 60 años.",
"Se excluyeron registros con SEMGES ≥ 100 ya que representan códigos de datos faltantes, no semanas de gestación reales. El rango biológico válido es aproximadamente entre 20 y 42 semanas.",
"Se excluyeron registros con TOHITE ≥ 50 para eliminar códigos especiales de datos faltantes. Es biológicamente improbable que una persona tenga 50 o más hijos.",
"Se excluyeron registros con TOHIVI ≥ 50 bajo el mismo criterio de plausibilidad biológica y para eliminar códigos especiales.",
"Se filtraron solo meses válidos (1 a 12), descartando valores fuera de rango que podrían representar errores de digitación o códigos especiales.",
"En análisis de contingencia y boxplots comparativos se excluyó el código 9 (no especificado) de la variable SEXO para enfocarse en las categorías informativas (1=Masculino, 2=Femenino).",
"Se acotó el análisis de tendencia temporal al período 2009-2023, que corresponde al rango de años con datos completos y consistentes del dataset.",
"Los códigos numéricos 99, 999 y 9999 fueron identificados como representaciones de datos faltantes o no especificados en el sistema de registro. Se contabilizaron para medir la calidad de los datos."
),
Variables_Afectadas = c(
"Todas las variables numéricas y categóricas",
"EDADM, SEMGES, TOHITE, TOHINM, TOHIVI",
"EDADM",
"SEMGES",
"TOHITE",
"TOHIVI",
"MESOCU",
"SEXO",
"AÑOREG",
"EDADM, SEMGES, TOHITE, TOHINM, TOHIVI, ESCOLAM"
),
Seccion_Aplicada = c(
"Estadísticas descriptivas, pruebas de normalidad, correlaciones, tablas de frecuencia, gráficos",
"Boxplots comparativos, gráficos de densidad",
"Gráficos de dispersión (Edad vs Semanas, Edad vs Hijos), boxplots por grupo",
"Gráficos de dispersión (Edad vs Semanas, Semanas vs Hijos Vivos)",
"Gráfico de dispersión (Edad vs Total Hijos)",
"Gráfico de dispersión (Semanas vs Hijos Vivos)",
"Gráfico de distribución mensual de ocurrencias",
"Barras agrupadas (Sexo vs Asistencia), boxplots por grupo",
"Gráfico de tendencia temporal",
"Detección de valores atípicos, heatmap de datos faltantes"
),
stringsAsFactors = FALSE
)
operaciones_limpieza %>%
kable(
caption = "Tabla: Documentación Completa de Operaciones de Limpieza de Datos",
col.names = c("#", "Operación", "Justificación", "Variables Afectadas", "Sección Aplicada"),
align = c('c', 'l', 'l', 'l', 'l')
) %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed"),
full_width = TRUE,
font_size = 11
) %>%
row_spec(0, bold = TRUE, color = "white", background = "#d35400") %>%
column_spec(2, width = "15em") %>%
column_spec(3, width = "25em") %>%
scroll_box(width = "100%", height = "600px")| # | Operación | Justificación | Variables Afectadas | Sección Aplicada |
|---|---|---|---|---|
| 1 | Eliminación de valores NA (na.omit / !is.na) | Los registros con valores faltantes (NA) fueron excluidos en cálculos estadísticos, gráficos y tablas de frecuencia para evitar distorsiones en medias, medianas, correlaciones y pruebas de normalidad. | Todas las variables numéricas y categóricas | Estadísticas descriptivas, pruebas de normalidad, correlaciones, tablas de frecuencia, gráficos |
| 2 | Exclusión de códigos especiales ≥ 900 | Variables como EDADM, SEMGES, TOHITE, TOHINM y TOHIVI utilizan códigos numéricos altos (≥ 900) para representar información no disponible. Estos valores fueron excluidos en boxplots y gráficos de densidad para que las distribuciones reflejen solo datos reales. | EDADM, SEMGES, TOHITE, TOHINM, TOHIVI | Boxplots comparativos, gráficos de densidad |
| 3 | Filtro de edad de la madre (EDADM < 100) | Se excluyeron registros con EDADM ≥ 100 ya que estos valores corresponden a códigos de datos faltantes (99, 999) y no a edades reales. La edad máxima biológicamente plausible para una madre es menor a 60 años. | EDADM | Gráficos de dispersión (Edad vs Semanas, Edad vs Hijos), boxplots por grupo |
| 4 | Filtro de semanas de gestación (SEMGES < 100) | Se excluyeron registros con SEMGES ≥ 100 ya que representan códigos de datos faltantes, no semanas de gestación reales. El rango biológico válido es aproximadamente entre 20 y 42 semanas. | SEMGES | Gráficos de dispersión (Edad vs Semanas, Semanas vs Hijos Vivos) |
| 5 | Filtro de total hijos tenidos (TOHITE < 50) | Se excluyeron registros con TOHITE ≥ 50 para eliminar códigos especiales de datos faltantes. Es biológicamente improbable que una persona tenga 50 o más hijos. | TOHITE | Gráfico de dispersión (Edad vs Total Hijos) |
| 6 | Filtro de total hijos vivos (TOHIVI < 50) | Se excluyeron registros con TOHIVI ≥ 50 bajo el mismo criterio de plausibilidad biológica y para eliminar códigos especiales. | TOHIVI | Gráfico de dispersión (Semanas vs Hijos Vivos) |
| 7 | Validación de meses (MESOCU entre 1 y 12) | Se filtraron solo meses válidos (1 a 12), descartando valores fuera de rango que podrían representar errores de digitación o códigos especiales. | MESOCU | Gráfico de distribución mensual de ocurrencias |
| 8 | Exclusión de sexo no especificado (SEXO ∈ {1, 2}) | En análisis de contingencia y boxplots comparativos se excluyó el código 9 (no especificado) de la variable SEXO para enfocarse en las categorías informativas (1=Masculino, 2=Femenino). | SEXO | Barras agrupadas (Sexo vs Asistencia), boxplots por grupo |
| 9 | Acotamiento del rango temporal (2009-2023) | Se acotó el análisis de tendencia temporal al período 2009-2023, que corresponde al rango de años con datos completos y consistentes del dataset. | AÑOREG | Gráfico de tendencia temporal |
| 10 | Identificación de códigos 99, 999, 9999 como datos faltantes | Los códigos numéricos 99, 999 y 9999 fueron identificados como representaciones de datos faltantes o no especificados en el sistema de registro. Se contabilizaron para medir la calidad de los datos. | EDADM, SEMGES, TOHITE, TOHINM, TOHIVI, ESCOLAM | Detección de valores atípicos, heatmap de datos faltantes |
n_total <- nrow(datos)
impacto <- data.frame(
Filtro = c(
"Registros originales",
"NA en EDADM",
"NA en SEMGES",
"EDADM ≥ 100 (códigos especiales)",
"SEMGES ≥ 100 (códigos especiales)",
"TOHITE ≥ 50 (códigos especiales)",
"TOHIVI ≥ 50 (códigos especiales)",
"SEXO = 9 (no especificado)",
"MESOCU fuera de rango (1-12)",
"Códigos 99/999/9999 en cualquier variable numérica"
),
Registros_Afectados = c(
n_total,
sum(is.na(datos$EDADM)),
sum(is.na(datos$SEMGES)),
if("EDADM" %in% names(datos)) sum(datos$EDADM >= 100, na.rm = TRUE) else 0,
if("SEMGES" %in% names(datos)) sum(datos$SEMGES >= 100, na.rm = TRUE) else 0,
if("TOHITE" %in% names(datos)) sum(datos$TOHITE >= 50, na.rm = TRUE) else 0,
if("TOHIVI" %in% names(datos)) sum(datos$TOHIVI >= 50, na.rm = TRUE) else 0,
if("SEXO" %in% names(datos)) sum(datos$SEXO == 9, na.rm = TRUE) else 0,
if("MESOCU" %in% names(datos)) sum(datos$MESOCU < 1 | datos$MESOCU > 12, na.rm = TRUE) else 0,
sum(sapply(datos[sapply(datos, is.numeric)], function(x) sum(x %in% c(99, 999, 9999), na.rm = TRUE)))
),
stringsAsFactors = FALSE
)
impacto$Porcentaje <- round(impacto$Registros_Afectados / n_total * 100, 2)
impacto$Porcentaje[1] <- 100.00
impacto %>%
mutate(Registros_Afectados = format(Registros_Afectados, big.mark = ",")) %>%
kable(
caption = "Tabla: Impacto Cuantitativo de cada Operación de Limpieza",
col.names = c("Filtro / Condición", "Registros Afectados", "% del Total"),
align = c('l', 'r', 'r')
) %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE,
position = "center"
) %>%
row_spec(0, bold = TRUE, color = "white", background = "#d35400") %>%
row_spec(1, bold = TRUE, background = "#f0f0f0")| Filtro / Condición | Registros Afectados | % del Total |
|---|---|---|
| Registros originales | 41,623 | 100.00 |
| NA en EDADM | 0 | 0.00 |
| NA en SEMGES | 0 | 0.00 |
| EDADM ≥ 100 (códigos especiales) | 1,195 | 2.87 |
| SEMGES ≥ 100 (códigos especiales) | 1,310 | 3.15 |
| TOHITE ≥ 50 (códigos especiales) | 19,353 | 46.50 |
| TOHIVI ≥ 50 (códigos especiales) | 16,343 | 39.26 |
| SEXO = 9 (no especificado) | 191 | 0.46 |
| MESOCU fuera de rango (1-12) | 0 | 0.00 |
| Códigos 99/999/9999 en cualquier variable numérica | 75,016 | 180.23 |
Notas Importantes sobre la Limpieza:
## R version 4.3.1 (2023-06-16)
## Platform: aarch64-apple-darwin20 (64-bit)
## Running under: macOS 26.2
##
## Matrix products: default
## BLAS: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.11.0
##
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
##
## time zone: America/Guatemala
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] cluster_2.1.4 corrplot_0.95 gridExtra_2.3 kableExtra_1.4.0
## [5] knitr_1.50 ggplot2_3.4.2 nortest_1.0-4 moments_0.14.1
## [9] tidyr_1.3.0 dplyr_1.1.2
##
## loaded via a namespace (and not attached):
## [1] sass_0.4.10 utf8_1.2.3 generics_0.1.3 xml2_1.3.8
## [5] lattice_0.21-8 stringi_1.7.12 digest_0.6.33 magrittr_2.0.3
## [9] evaluate_1.0.4 grid_4.3.1 RColorBrewer_1.1-3 fastmap_1.2.0
## [13] Matrix_1.5-4.1 jsonlite_2.0.0 mgcv_1.8-42 purrr_1.0.1
## [17] fansi_1.0.4 viridisLite_0.4.2 scales_1.2.1 textshaping_1.0.1
## [21] jquerylib_0.1.4 cli_3.6.1 rlang_1.1.1 splines_4.3.1
## [25] munsell_0.5.0 withr_2.5.0 cachem_1.1.0 yaml_2.3.10
## [29] tools_4.3.1 colorspace_2.1-0 vctrs_0.6.3 R6_2.5.1
## [33] lifecycle_1.0.3 stringr_1.5.0 pkgconfig_2.0.3 pillar_1.9.0
## [37] bslib_0.9.0 gtable_0.3.3 glue_1.6.2 systemfonts_1.2.3
## [41] xfun_0.52 tibble_3.2.1 tidyselect_1.2.1 rstudioapi_0.17.1
## [45] farver_2.1.1 nlme_3.1-162 htmltools_0.5.8.1 rmarkdown_2.29
## [49] svglite_2.2.1 labeling_0.4.2 compiler_4.3.1
Fin del Análisis Exploratorio
Documento generado el 16 de February de 2026 a las 00:45:57